package ca.paulshin.yunatube.http;

import static ca.paulshin.yunatube.database.YuNaTubeSqliteDatabase.getInstance;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.util.Pair;
import ca.paulshin.yunatube.R;
import ca.paulshin.yunatube.YunaTubeApplication;
import ca.paulshin.yunatube.common.Constants;
import ca.paulshin.yunatube.common.Preference;
import ca.paulshin.yunatube.common.Utils;
import ca.paulshin.yunatube.common.Utils.Network;
import ca.paulshin.yunatube.database.YuNaTubeSqliteDatabase;

public class YouTubeDataLoader extends YunaTubeHttpClient {
	private static int numOfMessages;
	private static YouTubeDataLoader loader = null;

	static {
		if (YunaTubeApplication.debuggable)
			numOfMessages = 20;
		else if (Utils.getConnectivity() == Network.MOBILE)
			numOfMessages = 50;
		else if (Utils.getConnectivity() == Network.WIFI)
			numOfMessages = 100;
		else
			numOfMessages = 20;

		loader = null;
	}

	public static YouTubeDataLoader getLoaderInstance() {
		if (loader == null)
			loader = new YouTubeDataLoader();
		return loader;
	}

	/*
	 * Loading stuff for main page
	 */
	public synchronized int loadXMLVersion(String url) {
		JSONObject versionObj = getJSONObject(Constants.YOUNATUBE_COUNTER_URL);
		String version = (String) (versionObj.get("version"));
		return Integer.parseInt(version);
	}

	public synchronized List<String> loadNotices() {
		final String url = Utils.getString(YunaTubeApplication.debuggable ? R.string.test_notices_url : R.string.notices_url);
		List<String> noticesList;

		JSONObject noticesObj = getJSONObject(url);
		String version = (String) (noticesObj.get("version"));
		JSONArray notices = (JSONArray) (noticesObj.get("notices"));

		noticesList = new ArrayList<String>();
		noticesList.add(version);
		for (Object notice : notices) {
			Object titleObj = ((JSONObject) notice).get("title");
			String title = (String) titleObj;
			noticesList.add(title);
		}

		return noticesList;
	}

	public synchronized Pair<String, String> loadFact() {
		final String url = Utils.getString(YunaTubeApplication.debuggable ? R.string.yunafact_test_url : R.string.yunafact_url);
		JSONObject factObj = getJSONObject(url);
		String fact = (String) (factObj.get("fact"));
		fact = fact.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;", "&");
		String photo = (String) (factObj.get("today_photo"));

		return new Pair<String, String>(fact, photo);
	}

	/*
	 * Load YouTube data
	 */
	public synchronized boolean loadXML() {
		int rand = (int) (Math.random() * 1000000);
		final String url = Utils.getString(YunaTubeApplication.debuggable ? R.string.test_xml_url : R.string.xml_url) + "?dummy=" + rand;
		Preference.put(YuNaTubeSqliteDatabase.IS_DB_AVAILABLE, false);

		Document doc = getXMLDocument(url);

		// Load youtube
		NodeList mcats = doc.getElementsByTagName("maincateg");

		for (int i = 0; i < mcats.getLength(); i++) {
			String mcat_type = mcats.item(i).getAttributes().getNamedItem("type").getNodeValue();
			String mcat_note = mcats.item(i).getAttributes().getNamedItem("note").getNodeValue();

			Element mcatElement = ((Element) mcats.item(i));
			NodeList cats = mcatElement.getElementsByTagName("category");
			for (int j = 0; j < cats.getLength(); j++) {
				String cat_type = cats.item(j).getAttributes().getNamedItem("title").getNodeValue();
				String cat_note = cats.item(j).getAttributes().getNamedItem("note").getNodeValue();

				Element catElement = ((Element) cats.item(j));
				NodeList clips = catElement.getElementsByTagName("clip");

				for (int k = 0; k < clips.getLength(); k++) {
					String clip_title = clips.item(k).getAttributes().getNamedItem("title").getNodeValue();
					String clip_url = clips.item(k).getAttributes().getNamedItem("url").getNodeValue();
					boolean clip_isNew = clips.item(k).getAttributes().getNamedItem("isNew").getNodeValue().equals("0");
					String clip_note = clips.item(k).getAttributes().getNamedItem("note").getNodeValue();

					if (clip_note.equals("")) {
						getInstance().insertEntity(mcat_type, cat_type, clip_title, clip_url);
					}
				}
			}
		}

		Preference.put(YuNaTubeSqliteDatabase.IS_DB_AVAILABLE, true);
		return true;
	}

	/*
	 * Handle comments
	 */
	public synchronized List<String[]> loadComments(List<String[]> commentsList, String ytId, int lastIndex) {
		String url = Constants.YOUTUBE_COMMENT_RETRIEVE;
		List<NameValuePair> params = new LinkedList<NameValuePair>();
		params.add(new BasicNameValuePair("ytid", ytId));
		params.add(new BasicNameValuePair("numOfMessages", String.valueOf(numOfMessages)));
		params.add(new BasicNameValuePair("lastIndex", String.valueOf(lastIndex)));
		url = Utils.getParameterizedUrl(url, params);

		JSONArray messages = getJSONArray(url);

		for (Object message : messages) {
			Object _report = ((JSONObject) message).get("report");
			String report = (String) _report;
			if (Integer.parseInt(report) > Constants.TO_YUNA_REPORT_FILTER) {
				continue;
			}
			Object _id = ((JSONObject) message).get("id");
			String id = (String) _id;
			Object _username = ((JSONObject) message).get("username");
			String username = (String) _username;
			Object _message = ((JSONObject) message).get("message");
			String msg = (String) _message;
			Object _time = ((JSONObject) message).get("time");
			String time = (String) _time;
			Object _device = ((JSONObject) message).get("device");
			String device = (String) _device;
			Object _isfirst = ((JSONObject) message).get("isfirst");
			String isfirst = (String) _isfirst;
			commentsList.add(new String[] { id, username, msg, time, device, report, isfirst });
		}

		return commentsList;
	}

	public synchronized List<String[]> loadMessages(List<String[]> messagesList, int lastIndex) {
		String url = Constants.TO_YUNA_RETRIEVE;
		List<NameValuePair> params = new LinkedList<NameValuePair>();
		params.add(new BasicNameValuePair("numOfMessages", String.valueOf(numOfMessages)));
		params.add(new BasicNameValuePair("lastIndex", String.valueOf(lastIndex)));
		url = Utils.getParameterizedUrl(url, params);

		JSONArray messages = getJSONArray(url);

		for (Object message : messages) {
			Object _report = ((JSONObject) message).get("report");
			String report = (String) _report;
			if (Integer.parseInt(report) > Constants.TO_YUNA_REPORT_FILTER) {
				continue;
			}
			Object _id = ((JSONObject) message).get("id");
			String id = (String) _id;
			Object _username = ((JSONObject) message).get("username");
			String username = (String) _username;
			Object _message = ((JSONObject) message).get("message");
			String msg = (String) _message;
			Object _time = ((JSONObject) message).get("time");
			String time = (String) _time;
			Object _device = ((JSONObject) message).get("device");
			String device = (String) _device;
			messagesList.add(new String[] { id, username, msg, time, device, report });
		}

		return messagesList;
	}

	public synchronized Boolean sendMessage(String url) {
		return post(url);
	}
}
